﻿

#include "font.h"


//  #include <dxerr.h>
//  #pragma comment(lib , "dxerr.lib")

namespace d3dx9_dynamic_load
{

	HRESULT Font::DrawStrA( const char* str ) const
	{
		HRESULT hr=0;

		RECT rec;
		rec.left   = m_posx;
		rec.top    = m_posy;
		rec.right    = rec.left  +  2000 ;
		rec.bottom   = rec.top   +  2000 ;

		// DT_BOTTOM Justifies the text to the bottom of the rectangle. 
		// This value must be combined with DT_SINGLELINE.

		// DT_CALCRECT Determines the width and height of the rectangle. 
		// If there are multiple lines of text, DrawText uses the 
		// width of the rectangle pointed to by the pRect parameter 
		// and extends the base of the rectangle to bound the 
		// last line of text. If there is only one line of text, 
		// DrawText modifies the right side of the rectangle
		// so that it bounds the last character in the line. 
		// In either case, DrawText returns the height of the formatted 
		// text but does not draw the text.

		// DT_CENTER Centers text horizontally in the rectangle.

		// DT_EXPANDTABS Expands tab characters. 
		// The default number of characters per tab is eight.

		// DT_LEFT Aligns text to the left.

		// DT_NOCLIP Draws without clipping. DrawText is somewhat 
		// faster when DT_NOCLIP is used.

		// DT_RIGHT Aligns text to the right.

		// DT_RTLREADING Displays text in right-to-left reading order for bidirectional
		// text when a Hebrew or Arabic font is selected.
		// The default reading order for all text is 
		// left-to-right.

		// DT_SINGLELINE Displays text on a single line only. 
		// Carriage returns and line feeds do not break the line.

		// DT_TOP Top-justifies text.

		// DT_VCENTER Centers text vertically (single line only).

		// DT_WORDBREAK Breaks words. Lines are automatically broken between words 
		// if a word would extend past the edge of the rectangle
		// specified by the pRect parameter. A carriage 
		// return/line feed sequence also breaks the line.

 

		m_lastResult = m_pfont->DrawTextA(NULL, str, -1, &rec, m_format, m_color );

		if(m_lastResult == 0) // INT m_lastResult;
		{
			// const char* errstr = DXGetErrorStringA(hr);
			// assert( hr==0 && " warning: operation   FALSE " );
			assert(  false && " failed operation ");
			return E_FAIL;
		}
 
 
		return hr;
	}

	HRESULT Font::DrawStrW(const WCHAR* str) const 
	{
		HRESULT hr=0;

		RECT rec;
		rec.left   = m_posx;
		rec.top    = m_posy;
		rec.right    = rec.left  +  2000 ;
		rec.bottom   = rec.top   +  2000 ;
		 

		m_lastResult = m_pfont->DrawTextW(NULL, str, -1, &rec, m_format, m_color );

		if(m_lastResult == 0) // INT m_lastResult;
		{
			// const char* errstr = DXGetErrorStringA(hr);
			// assert( hr==0 && " warning: operation   FALSE " );
			assert(  false && " failed operation ");
			return E_FAIL;
		}


		return hr;
	}


	HRESULT Font::DrawFormatA(const char* _Format, ... ) const
	{
		HRESULT hr=0;

		static char ss[8192] = {'\0'};
		ss[0] = 0;

		va_list ap;	   
		va_start( ap, _Format );
		vsprintf( ss, _Format, ap );
		va_end( ap );

		hr |= DrawStrA(ss);


		return hr;
	}

	HRESULT Font::DrawFormatW(const WCHAR* _Format, ... ) const
	{

		HRESULT hr=0;

		static wchar_t ss[8192] = {L'\0'};
		ss[0] = 0;

 
		//int vsnprintf(
		//	char *buffer,
		//	size_t count,
		//	const char *format,
		//	va_list argptr 
		//	);
		//int _vsnprintf(
		//	char *buffer,
		//	size_t count,
		//	const char *format,
		//	va_list argptr 
		//	);
		//int _vsnprintf_l(
		//	char *buffer,
		//	size_t count,
		//	const char *format,
		//	locale_t locale,
		//	va_list argptr 
		//	);
		//int _vsnwprintf(
		//	wchar_t *buffer,
		//	size_t count,
		//	const wchar_t *format,
		//	va_list argptr 
		//	);
		//int _vsnwprintf_l(
		//	wchar_t *buffer,
		//	size_t count,
		//	const wchar_t *format,
		//	locale_t locale,
		//	va_list argptr 
		//	);
		//template <size_t size>
		//int vsnprintf(
		//	char (&buffer)[size],
		//	size_t count,
		//	const char *format,
		//	va_list argptr 
		//	); // C++ only
		//template <size_t size>
		//int _vsnprintf(
		//	char (&buffer)[size],
		//	size_t count,
		//	const char *format,
		//	va_list argptr 
		//	); // C++ only
		//template <size_t size>
		//int _vsnprintf_l(
		//	char (&buffer)[size],
		//	size_t count,
		//	const char *format,
		//	locale_t locale,
		//	va_list argptr 
		//	); // C++ only
		//template <size_t size>
		//int _vsnwprintf(
		//	wchar_t (&buffer)[size],
		//	size_t count,
		//	const wchar_t *format,
		//	va_list argptr 
		//	); // C++ only
		//template <size_t size>
		//int _vsnwprintf_l(
		//	wchar_t (&buffer)[size],
		//	size_t count,
		//	const wchar_t *format,
		//	locale_t locale,
		//	va_list argptr 
		//	); // C++ only
 

		va_list ap;	   
		va_start( ap, _Format );
		_vsnwprintf(ss, 8192, _Format, ap);
//		vsprintf( ss, _Format, ap );

		va_end( ap );

		hr |= DrawStrW(ss);


		return hr;
	}





	//===============================================

namespace test
{
 

void do_test_drawfont(Font* const font)
{
	HRESULT hr=0;
	int x=10;
	int y=10;
   font->SetPosition(x,y);

   hr |=font->DrawStrA("sample string");
   
   y+= 15;
   font->SetPosition(x, y);
   font->DrawStrW(L"wide string");


   y+= 15;
   font->SetPosition(x, y);
   font->SetColor(234,78,34,200);
   font->DrawStrA("font->SetColor(234,78,34,200);");


   D3DCOLOR col;

	col= 0xffff0000;
	font->SetColor(col);
	y+= 15;
	font->SetPosition(x, y);
	font->DrawStrA("red string");


	col= 0xff00ff00;
	font->SetColor(col);
	y+= 15;
	font->SetPosition(x, y);
	font->DrawStrA("green string");


	col= 0xff0000ff;
	font->SetColor(col);
	y+= 15;
	font->SetPosition(x, y);
	font->DrawStrA("blue string");

	y+= 15;
	font->SetPosition(x, y);
	font->SetColorPink();
	font->DrawStrA("pink string");

	y+= 15;
	font->SetPosition(x, y);
	font->SetColorYellow();
	font->DrawStrA("pink yellow");

 

	// draw format astring
	font->SetPosition(100, 100);
	font->DrawFormatA("%s %i %f", "string", 555, 45.345f);

	// draw format wstring
	font->SetPosition(100, 120);
	font->DrawFormatW(L"%s %i %f", L"string", 555, 45.345f);



 //  assert(hr==0);
}


}

//==================================================

}

#ifdef __USE_TEST_D3DX9LOADER_FONT_CLASS__

#include <d3d9.h>
#pragma comment (lib,"d3d9.lib")

#define TITLE  L"Sample"

namespace d3dx9_dynamic_load
{

namespace test
{






	//-----------------------------------------------------------------------------
	// Global variables
	//-----------------------------------------------------------------------------
	LPDIRECT3D9         g_pD3D = NULL; // Used to create the D3DDevice
	LPDIRECT3DDEVICE9   g_pd3dDevice = NULL; // Our rendering device
	CD3DX9_Dll_Loader* g_loader = NULL;
	d3dx9_dynamic_load::Font* g_font;


	static HRESULT OnCreateDevice(HWND hWnd, IDirect3DDevice9* device )
	{
		HRESULT hr=0;




		return hr;
	}

	static void OnDestroyDevice()
	{
		//assert(false);

		if(g_font)
		{
			delete g_font;
			g_font = NULL;
		}
	}


	static HRESULT RecreateDevice(HWND hWnd )
	{
		HRESULT hr=0;

		if(g_pd3dDevice)
		{
			OnDestroyDevice();
			g_pd3dDevice->Release();
			g_pd3dDevice = NULL;
		}

		WINDOWINFO wi;
		::GetWindowInfo(hWnd, &wi);


		D3DPRESENT_PARAMETERS d3dpp;
		ZeroMemory( &d3dpp, sizeof( d3dpp ) );
		d3dpp.Windowed = TRUE;
		d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
		d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
		d3dpp.BackBufferWidth  = wi.rcClient.right-wi.rcClient.left;
		d3dpp.BackBufferHeight = wi.rcClient.bottom-wi.rcClient.top;


		// Create the Direct3D device. Here we are using the default adapter (most
		// systems only have one, unless they have multiple graphics hardware cards
		// installed) and requesting the HAL (which is saying we want the hardware
		// device rather than a software one). Software vertex processing is 
		// specified since we know it will work on all cards. On cards that support 
		// hardware vertex processing, though, we would see a big performance gain 
		// by specifying hardware vertex processing.
		if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
			hWnd,

			D3DCREATE_HARDWARE_VERTEXPROCESSING, //D3DCREATE_SOFTWARE_VERTEXPROCESSING,

			&d3dpp, &g_pd3dDevice ) ) )
		{
			return E_FAIL;
		}

		hr |= OnCreateDevice(hWnd, g_pd3dDevice);


		assert(hr==0);
		return hr;
	}


 
	static HRESULT InitD3D( HWND hWnd )
	{
		HRESULT hr=0;
		// Create the D3D object, which is needed to create the D3DDevice.
		if( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
			return E_FAIL;

		// Set up the structure used to create the D3DDevice. Most parameters are
		// zeroed out. We set Windowed to TRUE, since we want to do D3D in a
		// window, and then set the SwapEffect to "discard", which is the most
		// efficient method of presenting the back buffer to the display.  And 
		// we request a back buffer format that matches the current desktop display 
		// format.

		// Device state would normally be set here

		// CD3DX9_Dll_Loader* g_loader /
		g_loader = new CD3DX9_Dll_Loader();

		hr |= RecreateDevice(hWnd);

		return S_OK;
	}


 
	static VOID Cleanup()
	{
		if( g_pd3dDevice != NULL )
		{
			OnDestroyDevice();
			g_pd3dDevice->Release();
			g_pd3dDevice = NULL;
		}

		if( g_pD3D != NULL )
			g_pD3D->Release();


		delete g_loader;
	}



 
	static VOID Render()
	{
		HRESULT hr =0;
		static int count =0;

		if( NULL == g_pd3dDevice )
			return;

		// Clear the backbuffer to a blue color
		g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0, 0, 20 ), 1.0f, 0 );



		if(g_font==NULL)
		{
			d3dx9_dynamic_load::font_create_options opt;
			g_font = new d3dx9_dynamic_load::Font(g_pd3dDevice, g_loader, opt);
		}



		// Begin the scene
		if( SUCCEEDED( g_pd3dDevice->BeginScene() ) )
		{
			// Rendering of scene objects can happen here

			d3dx9_dynamic_load::test::do_test_drawfont(g_font);



			// End the scene
			g_pd3dDevice->EndScene();
		}

		// Present the backbuffer contents to the display
		hr |= g_pd3dDevice->Present( NULL, NULL, NULL, NULL );


		count++;
		//	assert(hr);

	}



 
	static LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
	{



		switch( msg )
		{
		case WM_DESTROY:
			Cleanup();
			PostQuitMessage( 0 );
			return 0;

		case WM_PAINT:
			Render();
			ValidateRect( hWnd, NULL );
			return 0;


		case WM_SIZE:
			RecreateDevice(hWnd);




			break;
		}

		return DefWindowProc( hWnd, msg, wParam, lParam );
	}





}
}

 
INT WINAPI wWinMain( HINSTANCE hInst, HINSTANCE, LPWSTR, INT )
{
	using namespace d3dx9_dynamic_load::test;
	UNREFERENCED_PARAMETER( hInst );

	// Register the window class
	WNDCLASSEXW wc =
	{
		sizeof( WNDCLASSEX ), CS_CLASSDC, MsgProc, 0L, 0L,
		GetModuleHandle( NULL ), NULL, NULL, NULL, NULL,
		TITLE, NULL
	};

	RegisterClassExW( &wc );

	// Create the application's window
	HWND hWnd = CreateWindowW( TITLE,  TITLE ,
		WS_OVERLAPPEDWINDOW, 100, 100, 300, 300,
		NULL, NULL, wc.hInstance, NULL );

	// Initialize Direct3D
	if( SUCCEEDED( InitD3D( hWnd ) ) )
	{
		// Show the window
		ShowWindow( hWnd, SW_SHOWDEFAULT );
		UpdateWindow( hWnd );

		// Enter the message loop
		MSG msg;
		while( GetMessage( &msg, NULL, 0, 0 ) )
		{
			TranslateMessage( &msg );
			DispatchMessage( &msg );
		}
	}

	UnregisterClassW( TITLE , wc.hInstance );
	return 0;
}



#undef TITLE 
#endif // #ifdef __USE_TEST_D3DX9LOADER_FONT_CLASS__

